package com.uxsino.simo.collector.connections;

import cn.chenlichao.wmi4j.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.uxsino.simo.connections.AbstractConnection;
import com.uxsino.simo.connections.exception.SimoConnectionException;
import com.uxsino.simo.connections.target.WMITarget;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.UnknownHostException;
import java.util.List;
import java.util.Map;

public class WMIConnection extends AbstractConnection<WMITarget> {
	private WMITarget wmiTarget;

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	private String namespace = "root\\cimv2";

	private SWbemLocator locator = null;
	private SWbemServices wbemServices = null;

	@Data
	private class WMICmd {

		private String className;

		private String[] propertys;

		WMICmd(String cmd, String args) {
			className = cmd;
			propertys = args.split(",");
		}

	}

	@Override
	public Object buildCmd(String cmdPattern, Map<String, String> args) {
		return new WMICmd(cmdPattern, args.get("args"));
	}

	@Override
	public int close() {
		connected = false;
		try {
			if (locator != null && locator.isConnected()) {
				locator.disconnect();
			}
			logger.info("WMI连接关闭！");
			return 1;
		} catch (WMIException e) {
			logger.error("", e);
			return 1;
		} finally {
			super.close();
		}
	}

	@Override
	public int connect(WMITarget target) {
		super.connect(target);
		wmiTarget = target;
		state = 0;
		connected = false;
		locator = new SWbemLocator(target.host, target.getUsername(), target.getPassword(), namespace);
		try {
			wbemServices = locator.connectServer();
			connected = true;
			state = 1;
		} catch (WMIException e) {
			logger.error("WMI访问[" + wmiTarget.host + "]被拒绝，请检测域名、用户名、密码是否正确，已经用户权限是否正确。", e.getMessage());
		} catch (UnknownHostException e) {
			logger.error("WMI访问[" + wmiTarget.host + "]被拒绝，请检测域名、用户名、密码是否正确，已经用户权限是否正确。", e.getMessage());
		}

		logger.info("WMI连接[" + wmiTarget.host + "]成功！");
		return state;
	}

	@Override
	public Object execCmd(Object cmdPattern) throws SimoConnectionException {
		JSONArray wql_results = new JSONArray();
		WMICmd wmiCmd = (WMICmd) cmdPattern;
		try {
			SWbemObjectSet s = wbemServices.execQuery(wmiCmd.getClassName());
			long now = System.currentTimeMillis();

			List<SWbemObject> data = Lists.newArrayList(s.iterator());
			StringBuffer buf = new StringBuffer("[");
			logger.info("cost time1111 : {}", System.currentTimeMillis() - now);
			data.parallelStream().forEach(itm->{
				try {
					buf.append(dataToJson(itm.getObjectText())).append(",");
				}catch (Exception e){
					logger.warn("wmi data process error: {}", e);
				}
			});
			buf.replace(buf.lastIndexOf(","), buf.lastIndexOf(",")+1, "");
			buf.append("]");
			wql_results = JSON.parseArray(buf.toString());
			logger.info("cost time : {}", System.currentTimeMillis() - now);
			logger.debug("执行WQL查询：" + wmiCmd.getClassName() + ",查询成功!");
		} catch (WMIException e) {
			logger.error("执行WQL查询:[" + wmiCmd.getClassName() + "],查询失败!");
			throw new SimoConnectionException(e);
		}
		return wql_results;
	}

	private String dataToJson(String str) {
		str = str.substring(str.indexOf("{"), str.lastIndexOf("}") +1);
		str = str.replaceAll("\"?\\;\\s{0,}((\r?\n?)|(\n?\r?))?\\}", "\"\n}");
		str = str.replaceAll("\"?\\;((\r?\n?)|(\n?\r?)){0,}\\s{0,}\\}{0}", "\",\n  \"");
		str = str.replaceAll("\\s{1,}\\=\\s{1,}\"?", "\" : \"");
		str = str.replaceAll("\\{((\r?\n?)|(\n?\r?))?\\s{1,}\\t{0,}", "{\n  \"");
		return str;
	}
	
	/*public static void main(String[] args) {
        WMITarget t = new WMITarget();
        t.host = "192.168.1.130";
        t.setUsername("administrator");
        try {
            t.setPassword(DESUtil.encrypt("Uxsino_test"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        WMIConnection w = new WMIConnection();
        try {
            w.connect(t);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, String> a = new HashMap<String, String>();
        a.put("args", "");
        Object cmd = w.buildCmd("SELECT * FROM Win32_OperatingSystem", a);
        try {
            System.out.println(w.execCmd(cmd));
        } catch (SimoConnectionException e) {
            e.printStackTrace();
        }
        w.close();
    }*/
}
